home *** CD-ROM | disk | FTP | other *** search
- /* GRAPHICS.C
- ************************************************************************
- * *
- * PC Scheme/Geneva 4.00 Borland C code *
- * *
- * (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- * (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- * *
- *----------------------------------------------------------------------*
- * *
- * Graphics Primitives *
- * *
- *----------------------------------------------------------------------*
- * *
- * Created by: L. Bartholdi Date: 3 Jun 1992 *
- * Revision history: *
- * - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- * *
- * ``In nomine omnipotentii dei'' *
- ************************************************************************/
-
- #include <stdarg.h>
- #include <stdlib.h>
- #include <graphics.h>
- #include <setjmp.h>
- #include "scheme.h"
-
- extern void far *_Cdecl _DDO_ADD; /* BGI state detect addresses */
- extern "C" {
- void far _GraphNotInstalled( void );
- }
-
- void far ErrorBGI( void ); /* Our BGI error handler */
- static jmp_buf jumper;
-
- #undef outtext /* this is a BGI routine, too */
-
- #define NUMARGS 62
-
- typedef union {
- char *s;
- REGPTR r;
- long i;
- }
- GRAPHARG;
-
- typedef struct {
- char opcode;
- void far *disp;
- } FARJUMP;
-
- void dopoly( REGPTR arg, void (far *proc)(int, const int far *) )
- {
- #define MAXPOLY 401 /* seems acceptable ... */
- typedef struct {
- int x, y;
- } POLYG;
- POLYG *poly;
- int len = 0;
-
- for( tmp_reg = *arg; tmp_reg.page; take_cdr(&tmp_reg), len++ );
- if (!(poly = (POLYG *) malloc(4 * len)))
- malloc_error("dopoly");
-
- for( len = 0 ; arg->page; take_cdr(arg), len++ )
- {
- tmp_reg = *arg, take_car(&tmp_reg);
- tm2_reg = tmp_reg, take_car(&tm2_reg), take_cdr(&tmp_reg);
- poly[len].x = tm2_reg.disp;
- poly[len].y = tmp_reg.disp;
- }
- (*proc)( len, (int *) poly );
- free( poly );
- }
-
- /* If you have to add a new function, add it in the right class and */
- /* increment the base ID of next classes in order to avoid */
- /* duplicate case in the switch statement. Don't forget to update */
- /* the similar table in graphics.s ! */
-
- #define CONTROL(x) ( 00 + (x) ) /* Control func IDs */
- #define DRAWING(x) ( 20 + (x) ) /* Drawing func IDs */
- #define FILLING(x) ( 40 + (x) ) /* Filling func IDs */
- #define WINDOWS(x) ( 60 + (x) ) /* Windows func IDs */
- #define TEXTCHR(x) ( 80 + (x) ) /* Text .CHR func IDs */
- #define PALETTE(x) ( 100 + (x) ) /* Palette func IDs */
- #define QUERIES(x) ( 120 + (x) ) /* State query func IDs */
-
- #define DOERROR(x) ( 140 + (x) ) /* Error simul. func IDs */
-
- int graphit( int n_args, ...)
- {
- char argMalloc[NUMARGS];
- GRAPHARG carg[NUMARGS];
- REGPTR sarg;
- REGPTR sresult;
- REG f1 = FIXNUM(0), f2 = FIXNUM(0);
- int i, j;
- va_list vlist;
- static lasterror;
- void far *farstr;
-
- va_start(vlist, n_args); /* skip until first argument */
- for (i = 0; i < n_args; i++) /* Warning: this structure may be wrong */
- sarg = va_arg(vlist, REGPTR); /* optimized (don't use i--)... (Thanks Borland) */
- carg[0].i = int2long(sarg);
- argMalloc[0] = 0;
- va_end(vlist);
-
- va_start(vlist, n_args); /* Convert every regptr */
- for (i = 1; i < n_args; i++) { /* Warning: this structure may be wrong */
- /* optimized (don't use i--)... (Thanks Borland) */
- sarg = va_arg(vlist, REGPTR);
- switch (ptype[CORRPAGE(sarg->page)]) {
- case STRTYPE:
- if ( carg[0].i == WINDOWS( 8 ) ) { /* put-image */
- farstr = reg2c(sarg)->string.buffer;
- argMalloc[n_args-i] = 0;
- } else { /* not put-image */
- carg[n_args-i].s = string_asciz(sarg);
- argMalloc[n_args-i] = 1;
- }
- break;
- case BIGTYPE:
- case FIXTYPE:
- carg[n_args-i].i = int2long(sarg);
- argMalloc[n_args-i] = 0;
- break;
- default:
- carg[n_args-i].r = sarg;
- argMalloc[n_args-i] = 0;
- }
- }
- sresult = va_arg(vlist, REGPTR); /* first arg was pushed first, so now it it the last arg... */
- va_end(vlist);
-
- if ( _DDO_ADD == &_GraphNotInstalled ) /* avoid abnormal exit */
- {
- _DDO_ADD = &ErrorBGI;
-
- /* patch _GraphNotInstalled. That's dirty, but
- a bug in graphics is graphdefaults() always calls _GNI */
- ((FARJUMP far *) _GraphNotInstalled)->opcode = 0xea;
- ((FARJUMP far *) _GraphNotInstalled)->disp = &ErrorBGI;
-
- }
-
- sresult->page = ADJPAGE(SPECFIX); /* assume we'll return this */
-
- switch( (i = setjmp( jumper )) == 0 ? carg[0].i : i ) /* ie func */
- {
- case CONTROL( 0 ):
- closegraph();
- break;
- case CONTROL( 1 ):
- detectgraph( &((int) f1.disp), &((int) f2.disp) );
- cons( sresult, &f1, &f2 );
- break;
- case CONTROL( 2 ):
- graphdefaults();
- break;
- case CONTROL( 3 ):
- sresult->disp = getgraphmode();
- break;
- case CONTROL( 4 ):
- getmoderange( carg[1].i, &((int) f1.disp), &((int) f2.disp) );
- cons( sresult, &f1, &f2 );
- break;
- case CONTROL( 5 ):
- initgraph( (int *) &(carg[1].i), (int *) &(carg[2].i), carg[3].s );
- break;
- case CONTROL( 6 ):
- sresult->disp = installuserdriver( carg[1].s, NULL );
- break;
- case CONTROL( 7 ):
- sresult->disp = installuserfont( carg[1].s );
- break;
- case CONTROL( 8 ):
- restorecrtmode();
- break;
- case CONTROL( 9 ):
- setgraphmode( carg[1].i );
- break;
- case CONTROL( 10 ):
- setwritemode( carg[1].i );
- break;
-
- case DRAWING( 0 ):
- arc( carg[1].i, carg[2].i, carg[3].i, carg[4].i, carg[5].i );
- longjmp( jumper, DRAWING( 4 ) );
- case DRAWING( 1 ):
- circle( carg[1].i, carg[2].i, carg[3].i );
- break;
- case DRAWING( 2 ):
- dopoly( carg[1].r, drawpoly );
- break;
- case DRAWING( 3 ):
- ellipse( carg[1].i, carg[2].i, carg[3].i, carg[4].i, carg[5].i, carg[6].i );
- case DRAWING( 4 ):
- {
- struct arccoordstype info;
- getarccoords( &info );
- f1.disp = info.xend, f2.disp = info.yend, cons( &tmp_reg, &f1, &f2 );
- cons( sresult, &tmp_reg, &nil_reg );
- f1.disp = info.xstart, f2.disp = info.ystart, cons( &tmp_reg, &f1, &f2 );
- cons( sresult, &tmp_reg, sresult );
- f1.disp = info.x, f2.disp = info.y, cons( &tmp_reg, &f1, &f2 );
- cons( sresult, &tmp_reg, sresult );
- }
- break;
- case DRAWING( 5 ):
- {
- long l1 = 0, l2 = 0;
- getaspectratio( (int *)&l1, (int *)&l2 );
- long2int( &f1, l1 ), long2int( &f2, l2 );
- cons( sresult, &f1, &f2 );
- }
- break;
- case DRAWING( 6 ):
- {
- struct linesettingstype info;
- long l1 = 0;
- getlinesettings( &info );
- f1.disp = info.thickness, cons( sresult, &f1, &nil_reg );
- l1 = info.upattern, long2int( &f1, l1), cons( sresult, &f1, sresult );
- f1.disp = info.linestyle, cons( sresult, &f1, sresult );
- }
- break;
- case DRAWING( 7 ):
- line( carg[1].i, carg[2].i, carg[3].i, carg[4].i );
- break;
- case DRAWING( 8 ):
- linerel( carg[1].i, carg[2].i );
- break;
- case DRAWING( 9 ):
- lineto( carg[1].i, carg[2].i );
- break;
- case DRAWING( 10 ):
- moveto( carg[1].i, carg[2].i );
- break;
- case DRAWING( 11 ):
- moverel( carg[1].i, carg[2].i );
- break;
- case DRAWING( 12 ):
- rectangle( carg[1].i, carg[2].i, carg[3].i, carg[4].i );
- break;
- case DRAWING( 13 ):
- setaspectratio( carg[1].i, carg[2].i );
- break;
- case DRAWING( 14 ):
- setlinestyle( carg[1].i, carg[2].i, carg[3].i );
- break;
-
- case FILLING( 0 ):
- bar( carg[1].i, carg[2].i, carg[3].i, carg[4].i );
- break;
- case FILLING( 1 ):
- bar3d( carg[1].i, carg[2].i, carg[3].i, carg[4].i, carg[5].i, carg[6].i );
- break;
- case FILLING( 2 ):
- fillellipse( carg[1].i, carg[2].i, carg[3].i, carg[4].i );
- break;
- case FILLING( 3 ):
- dopoly( carg[1].r, fillpoly );
- break;
- case FILLING( 4 ):
- floodfill( carg[1].i, carg[2].i, carg[3].i );
- break;
- case FILLING( 5 ):
- {
- char s[8];
- getfillpattern( s );
- alloc_block( sresult, STRTYPE, 8 );
- put_str( s, CORRPAGE(sresult->page), sresult->disp );
- }
- break;
- case FILLING( 6 ):
- {
- struct fillsettingstype fillinfo;
- getfillsettings( &fillinfo );
- f1.disp = fillinfo.pattern, f2.disp = fillinfo.color;
- cons( sresult, &f1, &f2 );
- }
- break;
- case FILLING( 7 ):
- pieslice( carg[1].i, carg[2].i, carg[3].i, carg[4].i, carg[5].i );
- break;
- case FILLING( 8 ):
- sector( carg[1].i, carg[2].i, carg[3].i, carg[4].i, carg[5].i, carg[6].i );
- break;
- case FILLING( 9 ):
- {
- char pattern[8];
- int count;
-
- tmp_reg = *carg[1].r;
- for( count = 0; count < 8; take_cdr(&tmp_reg), count++ )
- {
- if ( tmp_reg.page == nil_reg.page )
- tmp_reg = *carg[1].r;
- tm2_reg = tmp_reg; take_car(&tm2_reg);
- pattern[count] = tm2_reg.disp;
- }
- setfillpattern( pattern, carg[2].i );
- }
- break;
- case FILLING( 10 ):
- setfillstyle( carg[1].i, carg[2].i );
- break;
-
- case WINDOWS( 0 ):
- cleardevice();
- break;
- case WINDOWS( 1 ):
- setactivepage( carg[1].i );
- break;
- case WINDOWS( 2 ):
- setvisualpage( carg[1].i );
- break;
- case WINDOWS( 3 ):
- clearviewport();
- break;
- case WINDOWS( 4 ):
- {
- struct viewporttype viewinfo;
- getviewsettings( &viewinfo );
- f1.disp = viewinfo.clip, cons( sresult, &f1, &nil_reg );
- f1.disp = viewinfo.right, f2.disp = viewinfo.bottom;
- cons( &tmp_reg, &f1, &f2 );
- cons( sresult, &tmp_reg, sresult );
- f1.disp = viewinfo.left, f2.disp = viewinfo.top;
- cons( &tmp_reg, &f1, &f2 );
- cons( sresult, &tmp_reg, sresult );
- }
- break;
- case WINDOWS( 5 ):
- setviewport( carg[1].i, carg[2].i, carg[3].i, carg[4].i, carg[5].i );
- break;
- case WINDOWS( 6 ):
- alloc_block( sresult, STRTYPE, imagesize( carg[1].i, carg[2].i, carg[3].i, carg[4].i ) );
- getimage( carg[1].i, carg[2].i, carg[3].i, carg[4].i, reg2c(sresult)->string.buffer );
- break;
- case WINDOWS( 7 ):
- long2int( sresult, imagesize( carg[1].i, carg[2].i, carg[3].i, carg[4].i ) );
- break;
- case WINDOWS( 8 ):
- putimage( carg[1].i, carg[2].i, farstr, carg[4].i );
- break;
- case WINDOWS( 9 ):
- sresult->disp = getpixel( carg[1].i, carg[2].i );
- break;
- case WINDOWS( 10 ):
- putpixel( carg[1].i, carg[2].i, carg[3].i );
- break;
-
- case TEXTCHR( 0 ):
- {
- struct textsettingstype textinfo;
- gettextsettings( &textinfo );
- f1.disp = textinfo.vert, cons( sresult, &f1, &nil_reg );
- f1.disp = textinfo.horiz, cons( sresult, &f1, sresult );
- f1.disp = textinfo.charsize, cons( sresult, &f1, sresult );
- f1.disp = textinfo.direction, cons( sresult, &f1, sresult );
- f1.disp = textinfo.font, cons( sresult, &f1, sresult );
- }
- break;
- case TEXTCHR( 1 ):
- outtext( carg[1].s );
- break;
- case TEXTCHR( 2 ):
- outtextxy( carg[1].i, carg[2].i, carg[3].s );
- break;
- case TEXTCHR( 3 ):
- settextjustify( carg[1].i, carg[2].i );
- break;
- case TEXTCHR( 4 ):
- settextstyle( carg[1].i, carg[2].i, carg[3].i );
- break;
- case TEXTCHR( 5 ):
- setusercharsize( carg[1].i, carg[2].i, carg[3].i, carg[4].i );
- break;
- case TEXTCHR( 6 ):
- sresult->disp = textheight( carg[1].s );
- break;
- case TEXTCHR( 7 ):
- sresult->disp = textwidth( carg[1].s );
- break;
-
- case PALETTE( 0 ):
- sresult->disp = getbkcolor();
- break;
- case PALETTE( 1 ):
- sresult->disp = getcolor();
- break;
- case PALETTE( 2 ):
- {
- struct palettetype far *pal = getdefaultpalette();
- *sresult = nil_reg;
- for( int i = pal->size-1; i >= 0; i-- )
- f1.disp = pal->colors[i], cons( sresult, &f1, sresult );
- }
- break;
- case PALETTE( 3 ):
- sresult->disp = getmaxcolor();
- break;
- case PALETTE( 4 ):
- {
- struct palettetype pal;
- getpalette(&pal);
- *sresult = nil_reg;
- for( int i = pal.size-1; i >= 0; i-- )
- f1.disp = pal.colors[i], cons( sresult, &f1, sresult );
- }
- break;
- case PALETTE( 5 ):
- sresult->disp = getpalettesize();
- break;
- case PALETTE( 6 ):
- {
- struct palettetype pal;
- for( pal.size = 0; carg[1].r->page; take_cdr(carg[1].r), pal.size++ )
- {
- tmp_reg = *carg[1].r, take_car( &tmp_reg );
- pal.colors[pal.size] = tmp_reg.disp;
- }
- setallpalette( &pal );
- }
- break;
- case PALETTE( 7 ):
- setbkcolor( carg[1].i );
- break;
- case PALETTE( 8 ):
- setcolor( carg[1].i );
- break;
- case PALETTE( 9 ):
- setpalette( carg[1].i, carg[2].i );
- break;
- case PALETTE( 10 ):
- setrgbpalette( carg[1].i, carg[2].i, carg[3].i, carg[4].i );
- break;
-
- case QUERIES( 0 ):
- alloc_string( sresult, grapherrormsg( carg[1].i ) );
- break;
- case QUERIES( 1 ):
- sresult->disp = lasterror;
- break;
- case QUERIES( 2 ):
- alloc_string( sresult, getdrivername() );
- break;
- case QUERIES( 3 ):
- sresult->disp = getmaxmode();
- break;
- case QUERIES( 4 ):
- f1.disp = getmaxx(), f2.disp = getmaxy();
- cons( sresult, &f1, &f2 );
- break;
- case QUERIES( 5 ):
- alloc_string( sresult, getmodename( carg[1].i ) );
- break;
- case QUERIES( 6 ):
- f1.disp = getx(), f2.disp = gety();
- cons( sresult, &f1, &f2 );
- break;
-
- case DOERROR( 0 ):
- return lasterror = grNoInitGraph;
-
- default:
- return -1;
- }
-
- for ( i = 0; i < n_args; i++ ) { /* Free space for dynamic args */
- if ( argMalloc[i] )
- free( carg[i].s );
- }
-
- return lasterror = graphresult();
-
- }
-
- void ErrorBGI( void ) /* BGI error handler */
- {
- longjmp( jumper, DOERROR( 0 ) );
- }